﻿using System.Linq;
using System.Reflection;
using Autofac;
using DotNetStar.TheKing.Domain;
using DotNetStar.TheKing.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using SDDP;

namespace DotNetStar.TheKing.Services.Test
{
    using Domain.EventHandlers;
    using Microsoft.Extensions.Logging;

    public class ServiceTestBootstraper 
    {
        const string CONNECTION_STRING = "Data Source=.;Initial Catalog=DotNetStar;Integrated Security=true";
        private static readonly object _lock = new object();

        public ServiceTestBootstraper()
        {
            var builder = new ContainerBuilder();

            var dbContextBuilder = new DbContextOptionsBuilder<TheKingDbContext>();
            dbContextBuilder.UseSqlServer(CONNECTION_STRING);

            builder.Register(m => new TheKingDbContext(dbContextBuilder.Options)).As<DbContext>();
            builder.RegisterType<EFCoreDbContext>().As<IEFCoreDbContext>();

            builder.RegisterGeneric(typeof(EFCoreStorage<,>)).As(typeof(IStorage<,>));
            builder.Register(m=>new MemoryCache(new MemoryCacheOptions())).As<IMemoryCache>().SingleInstance();
            builder.RegisterType<Debug>().As<IDebug>().SingleInstance();
            builder.RegisterType<EventBus>().As<IEventBus>().SingleInstance();
            builder.RegisterType<LoggerFactory>().As<ILoggerFactory>().SingleInstance();

            var handlerTypes = Assembly.Load("DotNetStar.TheKing.Domain")
                 .ExportedTypes.Where(m =>m.BaseType!=null && m.IsClass &&m.BaseType.IsGenericType && m.BaseType.GetGenericTypeDefinition() == typeof(EventHandlerBase<>));
                

            builder.RegisterTypes(handlerTypes.ToArray());

            

            builder.RegisterAssemblyTypes(Assembly.Load("DotNetStar.TheKing.Services"));

            Container = builder.Build();

            Container.Resolve<IEventBus>()
                .Subscribe(Container.Resolve<UserPointEventHandler>())
                .Subscribe(Container.Resolve<UserOperationEventHandler>())
                ;
        }

        public static IContainer Container { get; set; }

        public static TService Resolve<TService>()
        => Container.Resolve<TService>();

        
    }
}
